﻿using System;
using System.Reflection;

namespace UFrame
{
    /// <summary>
    /// 不同类之间字段名相同，拷贝类的值
    /// 可以添加一个增量更新, 虽然没有什么用处
    /// </summary>
    public class RefCloneTool
    {
        public static T CloneClass<T>(Object sourceObj) where T : class, new()
        {
            Type type = typeof(T);
            object targetObj = Activator.CreateInstance(type);
            Type targetType = targetObj.GetType();
            Type sourceType = sourceObj.GetType();

            CloneWork(sourceType, targetType, sourceObj, targetObj);

            return (T)targetObj;
        }

        public static void CloneWork(Type sourceType, Type targetType, object sourceObj, object targetObj)
        {
            FieldInfo[] info =
                sourceType.GetFields(BindingFlags.Public | BindingFlags.NonPublic | BindingFlags.Instance);
            FieldInfo targetInfo = null;
            object val = null;
            for (int i = 0; i < info.Length; i++)
            {
                targetInfo = targetType.GetField(info[i].Name);
                if (targetInfo == null)
                {
                    Console.WriteLine(info[i].Name + " 没找到");
                    continue;
                }

                if (targetInfo.FieldType.IsClass)
                {
                    if (!(targetInfo.FieldType.Name == "String" || targetInfo.FieldType.FullName == "System.String"))
                    {
                        if (targetInfo.GetValue(targetObj) == null)
                        {
                            targetInfo.SetValue(targetObj, Activator.CreateInstance(targetInfo.FieldType));
                        }

                        //说明是普通的类
                        CloneWork(info[i].GetValue(sourceObj).GetType(), targetInfo.FieldType,
                            info[i].GetValue(sourceObj), targetInfo.GetValue(targetObj));
                    }
                }

                if (targetInfo != null)
                {
                    val = info[i].GetValue(sourceObj);
                    targetInfo.SetValue(targetObj, val);
                }
            }
        }
    }
}